package net.kazed.nextaction.database.serialize;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.ContentResolver;
import android.content.Context;
import android.database.CharArrayBuffer;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;

/**
 * Cursor to query summary of backup files.
 * @author Koert Zeilstra
 */
public class BackupSummaryCursor implements Cursor {

    public static final int INDEX_ID = 0;
    public static final int INDEX_NUMBER_OF_CONTEXTS = 1;
    public static final int INDEX_NUMBER_OF_TASKS = 2;
    
    private static final String SUFFIX = ".nab";
    private static final Map<String, Integer> COLUMN_NAME_MAPPING = new HashMap<String, Integer>();
    
    {
        COLUMN_NAME_MAPPING.put(BackupFileSummary.COLUMN_ID, INDEX_ID);
        COLUMN_NAME_MAPPING.put(BackupFileSummary.COLUMN_NUMBER_OF_CONTEXTS, INDEX_NUMBER_OF_CONTEXTS);
        COLUMN_NAME_MAPPING.put(BackupFileSummary.COLUMN_NUMBER_OF_TASKS, INDEX_NUMBER_OF_TASKS);
    }
    
    private List<SummaryRow> backupFileList;
    private int position = 0;
    
    /**
     * Constructor.
     * @param context Android context.
     * @param readContentSummary True if this cursor should read summary information from file.
     */
    public BackupSummaryCursor(Context context, boolean readContentSummary) {
        String[] files = context.fileList();
        backupFileList = new ArrayList<SummaryRow>(files.length);
        for (int i = 0; i < files.length; i++) {
            String fileName = files[i];
            if (fileName.endsWith(SUFFIX)) {
                String name = fileName.substring(0, fileName.length() - SUFFIX.length());
                try {
                    Long id = Long.parseLong(name);
                    SummaryRow summary = new SummaryRow();
                    summary.createDate = id;
                    backupFileList.add(summary);
                } catch (NumberFormatException e) {
                    // file is not a proper backup file with long ID
                }
            }
        }
    }
    
    /**
     * Constructor.
     * @param uri Query URI.
     * @param context Android context.
     * @param readContentSummary True if this cursor should read summary information from file.
     */
    public BackupSummaryCursor(Context context, Uri uri, boolean readContentSummary) {
        String id = uri.getLastPathSegment();
        if (TextUtils.isEmpty(id)) {
            throw new IllegalArgumentException("uri must contains file id: " + uri);
        }
        String fileName = id + ".nab";
        BackupFile backupFile = new BackupFile(fileName);
        BackupFileSummary backupSummary = backupFile.getBackupSummary(context);
        backupFileList = new ArrayList<SummaryRow>(1);
        SummaryRow summary = new SummaryRow();
        summary.createDate = Long.parseLong(id);
        summary.numberOfContexts = backupSummary.getNumberOfContexts();
        summary.numberOfTasks = backupSummary.getNumberOfTasks();
        backupFileList.add(summary);
    }
    
    @Override
    public void close() {
    }

    @Override
    public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
    }

    @Override
    public void deactivate() {
    }

    @Override
    public byte[] getBlob(int columnIndex) {
        return null;
    }

    @Override
    public int getColumnCount() {
        return 1;
    }

    @Override
    public int getColumnIndex(String columnName) {
        Integer index = COLUMN_NAME_MAPPING.get(columnName);
        if (index == null) {
            return 0;
        } else {
            return index.intValue();
        }
    }

    @Override
    public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
        return 0;
    }

    @Override
    public String getColumnName(int columnIndex) {
        return null;
    }

    @Override
    public String[] getColumnNames() {
        return null;
    }

    @Override
    public int getCount() {
        return backupFileList.size();
    }

    @Override
    public double getDouble(int columnIndex) {
        return 0;
    }

    @Override
    public Bundle getExtras() {
        return null;
    }

    @Override
    public float getFloat(int columnIndex) {
        return 0;
    }

    @Override
    public int getInt(int columnIndex) {
        int result = 0;
        SummaryRow row = backupFileList.get(position);
        switch(columnIndex) {
        case INDEX_NUMBER_OF_CONTEXTS:
            result = row.numberOfContexts;
            break;
        case INDEX_NUMBER_OF_TASKS:
            result = row.numberOfTasks;
            break;
        }
        return result;
    }

    @Override
    public long getLong(int columnIndex) {
        long result = 0;
        SummaryRow row = backupFileList.get(position);
        switch(columnIndex) {
        case INDEX_ID:
            result = row.createDate;
            break;
        }
        return result;
    }

    @Override
    public int getPosition() {
        return position;
    }

    @Override
    public short getShort(int columnIndex) {
        return 0;
    }

    @Override
    public String getString(int columnIndex) {
        String result = null;
        SummaryRow row = backupFileList.get(position);
        switch(columnIndex) {
        case INDEX_ID:
            result = Long.toString(row.createDate);
            break;
        }
        result = backupFileList.get(position).toString();
        return result;
    }

    @Override
    public boolean getWantsAllOnMoveCalls() {
        return false;
    }

    @Override
    public boolean isAfterLast() {
        return position >= backupFileList.size();
    }

    @Override
    public boolean isBeforeFirst() {
        return position < 0;
    }

    @Override
    public boolean isClosed() {
        return false;
    }

    @Override
    public boolean isFirst() {
        return position == 0;
    }

    @Override
    public boolean isLast() {
        return false;
    }

    @Override
    public boolean isNull(int columnIndex) {
        return false;
    }

    @Override
    public boolean move(int offset) {
        return false;
    }

    @Override
    public boolean moveToFirst() {
        position = 0;
        return !backupFileList.isEmpty();
    }

    @Override
    public boolean moveToLast() {
        position = backupFileList.size() - 1;
        return !backupFileList.isEmpty();
    }

    @Override
    public boolean moveToNext() {
        boolean result = false;
        if (position < backupFileList.size()) {
            position++;
            result = true;
        }
        return result;
    }

    @Override
    public boolean moveToPosition(int position) {
        boolean result = false;
        if (position >= 0 && position < backupFileList.size()) {
            this.position = position;
            result = true;
        }
        return result;
    }

    @Override
    public boolean moveToPrevious() {
        boolean result = false;
        if (position >= 0) {
            position--;
            result = true;
        }
        return result;
    }

    @Override
    public void registerContentObserver(ContentObserver observer) {
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
    }

    @Override
    public boolean requery() {
        return false;
    }

    @Override
    public Bundle respond(Bundle extras) {
        return null;
    }

    @Override
    public void setNotificationUri(ContentResolver cr, Uri uri) {
    }

    @Override
    public void unregisterContentObserver(ContentObserver observer) {
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
    }

    /**
     * Row data.
     */
    private class SummaryRow {
        public long createDate;
        public int numberOfContexts;
        public int numberOfTasks;
    }
    
}
